package com.tutou.ikgroup.websocket.netty;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.tutou.ikgroup.pojo.dto.ChatDTO;
import com.tutou.ikgroup.service.impl.UserChatInitImpl;
import com.tutou.ikgroup.websocket.ChannelContextUtil;
import com.tutou.ikuser.filter.JwtAuthenticationFilter;
import com.tutou.ikuser.pojo.po.User;
import com.tutou.ikuser.util.JwtUtil;
import io.jsonwebtoken.Jwts;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

import static com.tutou.ikuser.util.RedisConstants.LOGIN_TOKEN_KEY;

//一个非@Sharable的处理器不能被添加到ChannelPipeline中多次，设置为@Sharable可以多次添加到ChannelPipeline中
@ChannelHandler.Sharable
@Component
public class HandlerWebSocket extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    private static final Logger logger = LoggerFactory.getLogger(HandlerWebSocket.class);

    @Autowired
    private ChannelContextUtil channelContextUtil;

    @Autowired
    private UserChatInitImpl userChatInit;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 接收消息
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
        Channel channel = ctx.channel();
        //从channel中获取channelId的值
        Attribute<String> attribute = channel.attr(AttributeKey.valueOf(channel.id().toString()));
        String channelId = attribute.get();
        logger.info("收到消息用户ID为{}的信息{}", channelId, textWebSocketFrame.text());
        ctx.writeAndFlush(new TextWebSocketFrame("服务端返回信息：" + textWebSocketFrame.text()));
        //channelContextUtil.sendMessage(JSON.parseObject(textWebSocketFrame.text(), ChatDTO.class));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("有新的连接加入....");
        /*//从Redis获取用户ID
        userChatInit.getOfflineInfo(ctx.channel().id().toString());
        userChatInit.getOfflineChatroomInfo(ctx.channel().id().toString());
        userChatInit.getNewFriend(ctx.channel().id().toString());*/

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("有连接断开....");
        channelContextUtil.removeContext(ctx.channel());
    }

    //获取用户id，将用户id与channelId绑定，从而实现用户与channel的绑定，实现消息发送
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //判断客户端和服务器是否成功完成 WebSocket 握手
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            logger.info("握手成功~");
            WebSocketServerProtocolHandler.HandshakeComplete complete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
            HttpHeaders headers = complete.requestHeaders();
            //获取token信息验证用户合法
            String authorization = LOGIN_TOKEN_KEY + headers.get("Authorization");
            Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(authorization);
            if (userMap.isEmpty()) {
                ctx.writeAndFlush(new TextWebSocketFrame("请登录后重试~"));
                ctx.close();
                return;
            }
            User user = BeanUtil.copyProperties(userMap, User.class);
            logger.info("用户：{}", user);
            channelContextUtil.addContext(user.getUserId(), ctx.channel());
            //信息初始化
            userChatInit.getOfflineInfo(user.getUserId());
            userChatInit.getOfflineChatroomInfo(user.getUserId());
            userChatInit.getNewFriend(user.getUserId());
            userChatInit.getNewFriendPassOrReject(user.getUserId());
        } else {
            logger.error("WebSocket握手失败~");
        }
    }

    private User getTokenForUserId(String uri) {
        if (uri.isEmpty() || uri.indexOf("?") == -1) {
            return null;
        }
        String[] queryParams = uri.split("\\?");
        if (queryParams.length != 2) {
            return null;
        }
        String[] params = queryParams[1].split("=");
        if (params.length != 2) {
            return null;
        }
        logger.info(params[1]);
        //转为JSON格式后转对象
        String userJSON = JwtUtil.getUser(params[1])
                .replaceAll("([a-zA-Z0-9_$]+)=([^,}]+)", "\"$1\":\"$2\"")
                .replaceAll("\"null\"", "null")
                .replace("{", "{").replace("}", "}");
        return JSON.parseObject(userJSON, User.class);
    }
}
